package com.chaos.auth.config.granter.user;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.chaos.auth.api.data.TConfigData;
import com.chaos.auth.api.dto.token.UserAuthenticationToken;
import com.chaos.auth.api.dto.wechat.WeChatConfigInfoData;
import com.chaos.auth.api.dto.wechat.WeChatPublicLoginResData;
import com.chaos.auth.api.dto.wechat.WeChatUserPhoneInfoData;
import com.chaos.auth.helper.AESHelper;
import com.chaos.auth.helper.WeixinHelper;
import com.chaos.auth.service.TConfigService;
import com.chaos.auth.service.userdetails.UserByWxOpenIdDetailsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Map;

@Slf4j
@Component
public class UserByWxAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private TConfigService configService;

    @Autowired
    private UserByWxOpenIdDetailsService userByWxOpenIdDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Map<String, String> details = (Map<String, String>) authentication.getDetails();
        String code = details.get("code");
        String tenantId = details.get("tenantId");
        String encryptedData = details.get("encryptedData");
        String iv = details.get("iv");
        Assert.notNull(code, "code不能为空");
        Assert.notNull(tenantId, "商户号不能为空");
        Assert.notNull(encryptedData, "encryptedData不能为空");
        Assert.notNull(iv, "iv不能为空");
        Long longTenanttId = Long.valueOf(tenantId);
        log.info("iv:{}", iv);
        log.info("encryptedData:{}", encryptedData);
        //获取商户号配置
        TConfigData tConfigData = null;
//                configService.selectByConfigKeyAndTenantId(TConfigData.builder()
//                .key(CommonConstant.WX_APP_ID_SECRET_CONFIG)
//                .tenantId(longTenanttId)
//                .build());
        Assert.notNull(tConfigData, "获取商户配置信息异常");
        WeChatConfigInfoData configInfoData = JSON.parseObject(tConfigData.getConfigKey(), WeChatConfigInfoData.class);
        //微信登录
        String accessTokenUrl = WeixinHelper.getWebJsCode2SessionAccess(configInfoData.getAppId(), configInfoData.getSecret(), code);
        WeChatPublicLoginResData publicLoginResData = WeixinHelper.weChatPublicUserLogin(accessTokenUrl);
        Assert.notNull(publicLoginResData.getOpenid(), "获取微信信息异常！" + publicLoginResData.getErrmsg());
        //获取手机号
        String phoneNumberData = null;
        try {
            byte[] resultByte = AESHelper.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(publicLoginResData.getSessionKey()), Base64.decodeBase64(iv));
            phoneNumberData = new String(resultByte, StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取手机号异常：{}", e.getMessage());
            throw new DisabledException("获取手机号异常！");
        }
        Assert.notNull(phoneNumberData, "获取手机号为空");
        WeChatUserPhoneInfoData chatUserPhoneInfoData = JSON.parseObject(phoneNumberData, WeChatUserPhoneInfoData.class);
        String openId = publicLoginResData.getOpenid();
        UserDetails userDetails = userByWxOpenIdDetailsService.loadUserByWxOpenId(openId, null);
        UserAuthenticationToken result = new UserAuthenticationToken(userDetails);
        result.setDetails(authentication.getDetails());
        return result;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return UserAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
